import * as vscode from 'vscode';
import * as fs from 'fs';
import * as path from 'path';
// import { VerticalDiffManager } from '../../../src/diff/vertical/VerticalDiffManager';
import { LLMFactory } from '../../../core/llm/llmFactory';
import { BaseLLM } from '../../../core/llm/baseLLM';
import { ProxyService } from '../../../src/services/proxyService';
import { LoginService } from '../../../src/services/loginService';
import { AnalyticsService } from '../../../src/services/analyticsService';
import { Logger } from '../../../src/logger/Logger';

// 导入实体类型
import { FunctionInfo, BaseCommonCppContext, HarmonyCppPromptContext, DefsInFunc } from './entities/types';

// 导入处理器
import { CxxElementExtractor } from './processors/CxxElementExtractor';
import { ClassifyDefinitionsProcessor } from './processors/ClassifyDefinitionsProcessor';
import { CxxCustomizationProcessor } from './processors/CxxCustomizationProcessor';
import { OtherProcessor } from './processors/OtherProcessor';
import { FunctionCodeProcessor } from './processors/FunctionCodeProcessor';
import { FuncBasicInfoProcessor } from './processors/FuncBasicInfoProcessor';
import { HarmonyBranchMapProcessor } from './processors/HarmonyBranchMapProcessor';
import { StaticMethod } from './processors/StaticMethod';
import { TemplateMethod } from './processors/TemplateMethod';

// 导入工具函数
import { waitForTimeout } from './utils/utils';
import { TreeSitter } from '../../../core/treesitter/TreeSitter';
import { UnitTestPreviewPanel, UnitTestPreviewData } from './UnitTestPreviewPanel';
import { GNFileManager } from './GNFileManager';

// 常量定义
const HARMONY_TIMEOUT_MS = 30000;
const RESERVE_TIME_MS = 200;

export class UnitTestGenerator {
    
    /**
     * 终端DT C++定制化方法
     * @param document 文档对象
     * @param position 位置
     * @param unittestsDir 单元测试目录
     * @param utcoreTimeout 超时时间
     * @returns 提示上下文对象
     */
    public static async terminalDTCxxCustomization(
        document: vscode.TextDocument,
        position: vscode.Position,
        unittestsDir: string,
        utcoreTimeout: number
    ): Promise<Object | null> {
        Logger.info(`terminalDTCxxCustomization start.`);
        await TreeSitter.getInstance().init();
        const start = Date.now(); // 记录开始时间
        const res = await this.parseHarmonyTaskParameter(document, position, unittestsDir, utcoreTimeout) as HarmonyCppPromptContext | null;
        const end = Date.now(); // 记录结束时间
        const executionTime = end - start; // 计算执行时间
        TreeSitter.getInstance().clearCache();
        Logger.info(`terminalDTCxxCustomization time cost: ${executionTime}ms.result: ${JSON.stringify(res)}`);
        return res;
    }

    /**
     * 解析Harmony任务参数
     * @param document 文档对象
     * @param position 位置
     * @param unittestsDir 单元测试目录
     * @param utcoreTimeout 超时时间
     * @returns 提示上下文对象
     */
    public static async parseHarmonyTaskParameter(
        document: vscode.TextDocument,
        position: vscode.Position,
        unittestsDir: string,
        utcoreTimeout: number
    ): Promise<Object | null> {
        const start = Date.now(); // 记录开始时间
        const range = OtherProcessor.getFunctionRange(document, position);
        const functionInfo = await FuncBasicInfoProcessor.extract(document, position, range);
        CxxCustomizationProcessor.parseSignature(document, range, functionInfo);
        const commonContext: BaseCommonCppContext = await this.getBaseCommonCppContext(document, functionInfo, range);
        const pathMap = await HarmonyBranchMapProcessor.extract(commonContext.code || "", document.languageId);
        const end = Date.now(); // 记录结束时间
        const executionTime = end - start; // 计算执行时间
        const timeoutMs = (utcoreTimeout || HARMONY_TIMEOUT_MS) - executionTime;
        Logger.info(`parseHarmonyTaskParameter mustContext success time cost: ${executionTime} ms.remianing time: ${timeoutMs} ms`);

        if (timeoutMs <= 0) {
            return await this.getHarmonyDtMustUsePromptContext(document, functionInfo, commonContext, range, pathMap);
        }

        try {
            const promptPromise = this.getHarmonyCppContext(document, functionInfo, commonContext, range, pathMap, position, unittestsDir, timeoutMs);
            const res = await Promise.race([promptPromise, waitForTimeout(timeoutMs || HARMONY_TIMEOUT_MS)]);
            if (!res) {
                return await this.getHarmonyDtMustUsePromptContext(document, functionInfo, commonContext, range, pathMap);
            }
            return res;
        } catch (err) {
            Logger.error(`getHarmonyCppContext This request was aborted because it took more than ${timeoutMs || HARMONY_TIMEOUT_MS} ms`);
            return await this.getHarmonyDtMustUsePromptContext(document, functionInfo, commonContext, range, pathMap);
        }
    }

    /**
     * 获取HarmonyDT必须使用的提示上下文
     * @param document 文档对象
     * @param functionInfo 函数信息
     * @param commonContext 通用上下文
     * @param range 范围
     * @param pathMap 路径映射
     * @returns 提示上下文
     */
    private static async getHarmonyDtMustUsePromptContext(
        document: vscode.TextDocument,
        functionInfo: FunctionInfo,
        commonContext: BaseCommonCppContext,
        range: vscode.Range,
        pathMap: any[]
    ): Promise<HarmonyCppPromptContext | null> {
        const start = Date.now(); // 记录开始时间
        const addRowFunctionCode = HarmonyBranchMapProcessor.addLineNumber(functionInfo.code ?? '');
        const harmonyCppPromptContext: HarmonyCppPromptContext = {
            ...commonContext,
            is_static_method: await StaticMethod.extract(document, range, functionInfo),
            is_template_method: await TemplateMethod.extract(functionInfo),
            callee_method_class: {},
            returnType: '',
            sourceClass: '',
            sourceClassConstructors: {
                public: [],
                protected: [],
                private: []
            },
            sourceClassMembers: [],
            paramDefinitions: [],
            signature: functionInfo.signature || '',
            targetFunctionCode: functionInfo.code || '',
            addRowFunctionCode,
            modulePath: '/harmony' + document.uri.fsPath.replace(/^[A-Z]:/i, '').replace(/\\/g, '/'),
            sourceMethodBranchMap: [...pathMap],
            is_harmony_scenario: true,
            gmock_template_str: '',
            cpp_stub_template_str: '',
            funcCalledList: [],
            source_cls_namespace_name: '',
            existing_test_case: [],
            existing_test_suite: '',
            existing_gmock_def: [],
            existing_cpp_stub_def: [],
            interface_definitions: [],
            source_class_constructor_method: '',
            source_class_name_lower: '',
            init_head_macro: '',
            gmock_str: '',
            cppstub_str: '',
            source_class_fields: '',
            include_statement: '',
            using_namespace: '',
            other_str: ''
        };
        const end = Date.now(); // 记录结束时间
        const executionTime = end - start; // 计算执行时间
        Logger.info(`getHarmonyDtMustUsePromptContext success time cost: ${executionTime}ms.`);
        return harmonyCppPromptContext;
    }

    /**
     * 获取Harmony C++上下文
     * @param document 文档对象
     * @param functionInfo 函数信息
     * @param commonContext 通用上下文
     * @param range 范围
     * @param pathMap 路径映射
     * @param position 位置
     * @param unittestsDir 单元测试目录
     * @param utcoreTimeout 超时时间
     * @returns 提示上下文
     */
    private static async getHarmonyCppContext(
        document: vscode.TextDocument,
        functionInfo: FunctionInfo,
        commonContext: BaseCommonCppContext,
        range: vscode.Range,
        pathMap: any[],
        position: vscode.Position,
        unittestsDir: string,
        utcoreTimeout: number
    ): Promise<HarmonyCppPromptContext | null> {
        const start = Date.now(); // 记录开始时间
        try {
            const extractor = new CxxElementExtractor();
            const { symbolDefinitions } = await extractor.getElements({ doc: document, pos: position }, functionInfo);
            await CxxCustomizationProcessor.getSnippetDefinitions(document, range, symbolDefinitions);
            const definitionInFunction: DefsInFunc = await ClassifyDefinitionsProcessor.classifyDefinitions(symbolDefinitions, functionInfo);
            const { templateInstantiation, templateDeclar } = await CxxCustomizationProcessor.getTemplateStatment(document, functionInfo);
            const targetFunctionCode = functionInfo.code ? (`${templateDeclar}\r\n${functionInfo.code}\r\n${templateInstantiation}`) : '';
            const addRowFunctionCode = HarmonyBranchMapProcessor.addLineNumber(targetFunctionCode ?? '');
            const { gmockTemplateStr, cppStubTemplateStr, setFuncCalledList, interfaceDefinitions, allGmock, allCppStub, otherStr } =
                await CxxCustomizationProcessor.handleAllDefinitions(symbolDefinitions, functionInfo, pathMap);
            const { constructorsMethod, classNameLower, gmockStr, cppstubStr, classFields } =
                await CxxCustomizationProcessor.handleSourceMethod(functionInfo, definitionInFunction, allGmock, allCppStub, document.languageId);
            const usingNamespace = CxxCustomizationProcessor.getUsingNamespace(definitionInFunction.others.paramNamespace, definitionInFunction.classNamespace);
            const harmonyCppPromptContext: HarmonyCppPromptContext = {
                ...commonContext,
                is_static_method: await StaticMethod.extract(document, range, functionInfo),
                is_template_method: await TemplateMethod.extract(functionInfo),
                callee_method_class: {},
                returnType: definitionInFunction.return,
                sourceClass: definitionInFunction.class,
                sourceClassConstructors: definitionInFunction.classCtors,
                sourceClassMembers: definitionInFunction.classMembers,
                paramDefinitions: definitionInFunction.parameters.concat(definitionInFunction.others.classCtorsParamDefinition),
                signature: functionInfo.signature || '',
                targetFunctionCode,
                addRowFunctionCode,
                modulePath: '/harmony' + document.uri.fsPath.replace(/^[A-Z]:/i, '').replace(/\\/g, '/'),
                sourceMethodBranchMap: [...pathMap],
                is_harmony_scenario: true,
                gmock_template_str: gmockTemplateStr,
                cpp_stub_template_str: cppStubTemplateStr,
                funcCalledList: setFuncCalledList,
                source_cls_namespace_name: `${(definitionInFunction.classNamespace && usingNamespace) ?
                    definitionInFunction.classNamespace + ';' : definitionInFunction.classNamespace}${usingNamespace}`,
                existing_test_case: [],
                existing_test_suite: '',
                existing_gmock_def: [],
                existing_cpp_stub_def: [],
                interface_definitions: interfaceDefinitions,
                source_class_constructor_method: constructorsMethod,
                source_class_name_lower: classNameLower,
                init_head_macro: '',
                gmock_str: gmockStr,
                cppstub_str: cppstubStr,
                source_class_fields: classFields,
                include_statement: '',
                using_namespace: usingNamespace,
                other_str: otherStr,
            };
            const end = Date.now(); // 记录结束时间
            const executionTime = end - start; // 计算执行时间
            Logger.info(`getHarmonyCppContext success time cost: ${executionTime}ms.`);
            // 计算可以留给高耗时函数的执行时间，预留200ms
            const remainingTime = utcoreTimeout - executionTime - RESERVE_TIME_MS;
            const restart = Date.now(); // 记录开始时间
            const harmonyCppPromptContextIncludeReferences =
                await this.getHarmonyCppContextByreferencesTimeout(document, functionInfo,
                    unittestsDir,
                    definitionInFunction,
                    gmockStr,
                    cppstubStr,
                    harmonyCppPromptContext,
                    remainingTime);

            const reend = Date.now(); // 记录结束时间
            const reexecutionTime = reend - restart; // 计算执行时间
            Logger.info(`getHarmonyCppContextByreferencesTimeout end time cost: ${reexecutionTime}ms.`);
            return harmonyCppPromptContextIncludeReferences || harmonyCppPromptContext;
        } catch (error) {
            const end = Date.now(); // 记录结束时间
            const executionTime = end - start; // 计算执行时间
            Logger.error(`getHarmonyCppContext err time cost: ${executionTime}ms. err :${error}`);
            return null;
        }
    }

    /**
     * 通过引用超时获取Harmony C++上下文
     * @param document 文档对象
     * @param functionInfo 函数信息
     * @param unittestsDir 单元测试目录
     * @param definitionInFunction 函数内定义
     * @param gmockStr GMock字符串
     * @param cppstubStr C++存根字符串
     * @param harmonyCppPromptContext 提示上下文
     * @param remainingTime 剩余时间
     * @returns 更新后的提示上下文
     */
    private static async getHarmonyCppContextByreferencesTimeout(
        document: vscode.TextDocument,
        functionInfo: FunctionInfo,
        unittestsDir: string,
        definitionInFunction: DefsInFunc,
        gmockStr: string,
        cppstubStr: string,
        harmonyCppPromptContext: HarmonyCppPromptContext,
        remainingTime: number
    ): Promise<HarmonyCppPromptContext | null> {
        Logger.info(`getHarmonyCppContextByreferencesTimeout start .the maximum available time : ${remainingTime}ms.`);
        if (remainingTime <= 0) {
            return null;
        }
        try {
            const promptPromise = this.getHarmonyCppContextByreferences(document,
                functionInfo,
                unittestsDir,
                definitionInFunction,
                gmockStr,
                cppstubStr,
                harmonyCppPromptContext);
            await Promise.race([promptPromise, waitForTimeout(remainingTime)]);
            if (!promptPromise) {
                return null;
            }
            Logger.info(`getHarmonyCppContextByreferencesTimeout success`);
            return promptPromise;
        } catch (err) {
            Logger.error(`getHarmonyCppContextByreferencesTimeout This request was aborted because it took more than ${remainingTime} ms`);
            return null;
        }
    }

    /**
     * 通过引用获取Harmony C++上下文
     * @param document 文档对象
     * @param functionInfo 函数信息
     * @param unittestsDir 单元测试目录
     * @param definitionInFunction 函数内定义
     * @param gmockStr GMock字符串
     * @param cppstubStr C++存根字符串
     * @param harmonyCppPromptContext 提示上下文
     * @returns 更新后的提示上下文
     */
    private static async getHarmonyCppContextByreferences(
        document: vscode.TextDocument,
        functionInfo: FunctionInfo,
        unittestsDir: string,
        definitionInFunction: DefsInFunc,
        gmockStr: string,
        cppstubStr: string,
        harmonyCppPromptContext: HarmonyCppPromptContext
    ): Promise<HarmonyCppPromptContext | null> {
        const { includeStr, filterReferences } = await CxxCustomizationProcessor.getIncludeStatment(document, definitionInFunction, functionInfo);
        const { testCases, testSuite, gMock, cppStub } = await CxxCustomizationProcessor.getUTTest(document, unittestsDir, functionInfo.sourceFunc?.position);
        const headMacro = CxxCustomizationProcessor.getHeadMacroStr(gmockStr, cppstubStr, includeStr, filterReferences);
        return {
            ...harmonyCppPromptContext,
            existing_test_case: testCases,
            existing_test_suite: testSuite,
            existing_gmock_def: gMock,
            existing_cpp_stub_def: cppStub,
            init_head_macro: headMacro,
            include_statement: includeStr
        };
    }

    /**
     * 获取基础通用C++上下文
     * @param document 文档对象
     * @param functionInfo 函数信息
     * @param range 范围
     * @param rowInfo 是否包含行信息
     * @returns 基础上下文
     */
    private static async getBaseCommonCppContext(document: vscode.TextDocument, functionInfo: FunctionInfo, range: vscode.Range, rowInfo = false): Promise<BaseCommonCppContext> {
        const start = Date.now(); // 记录开始时间
        let commonContext: BaseCommonCppContext = {
            language: 'cpp',
            ide: vscode.env.appName || 'VSCode',
            code: FunctionCodeProcessor.extract(functionInfo.code || ""),
            origin_code: functionInfo.code || "",
            cls: functionInfo.sourceClassName || "",
            source_method_file_path: document.uri.fsPath,
            source_method_signature: functionInfo.signature,
            source_method_name: functionInfo.sourceFuncName || "",
        };
        if (rowInfo) {
            commonContext.start_row = range.start.line + 1;
            commonContext.end_row = range.end.line + 1;
        }
        const end = Date.now(); // 记录结束时间
        const executionTime = end - start; // 计算执行时间
        Logger.info(`getBaseCommonCppContext success time cost: ${executionTime}ms.`);
        return commonContext;
    }

    /**
     * 生成单元测试的主要方法
     * @param verticalDiffManager 垂直差异管理器
     * @param llmFactory LLM工厂
     * @param context 扩展上下文
     */
    public static async generateUnitTest(
        verticalDiffManager: any,
        llmFactory: LLMFactory,
        context: vscode.ExtensionContext
    ): Promise<void> {
        try {
            // 单元测试生成不需要登录，因为只使用本地GLM配置
            // 追踪事件（如果已登录）
            try {
                const loginService = LoginService.getInstance(context);
                const isLoggedIn = await loginService.isLoggedIn();
                if (isLoggedIn) {
                    AnalyticsService.getInstance(context).trackEvent('generateUnitTest');
                }
            } catch (error) {
                // 忽略登录检查错误，继续执行
                Logger.info('Skip login check for unit test generation');
            }

            // 获取当前编辑器
            const editor = vscode.window.activeTextEditor;
            if (!editor) {
                vscode.window.showErrorMessage('请打开一个文件后再使用此功能');
                return;
            }

            const document = editor.document;
            
            // 检查是否是C/C++文件
            if (document.languageId !== 'cpp' && document.languageId !== 'c') {
                vscode.window.showErrorMessage('此功能仅支持 C/C++ 文件');
                return;
            }

            const position = editor.selection.active;

            // 获取配置
            const config = vscode.workspace.getConfiguration('harmonypilot');
            const testDirectory = config.get<string>('unitTestDirectory', './tests');
            const timeout = config.get<number>('unitTestTimeout', 30000);
            const modelName = config.get<string>('unitTestModel', 'glm-4-flash');

            // 显示进度
            await vscode.window.withProgress({
                location: vscode.ProgressLocation.Notification,
                title: "生成单元测试",
                cancellable: true
            }, async (progress: vscode.Progress<{ increment?: number; message?: string }>, token: vscode.CancellationToken) => {
                progress.report({ increment: 0, message: "分析代码..." });

                Logger.info(`========== 开始生成单元测试 ==========`);
                Logger.info(`Document URI: ${document.uri.toString()}`);
                Logger.info(`Document fsPath: ${document.uri.fsPath}`);
                Logger.info(`Document languageId: ${document.languageId}`);
                Logger.info(`Test directory: ${testDirectory}`);

                // 调用terminalDTCxxCustomization获取上下文
                const promptContext = await this.terminalDTCxxCustomization(document, position, testDirectory, timeout);
                
                if (!promptContext) {
                    vscode.window.showErrorMessage('无法分析代码，请检查代码格式或光标是否在函数内');
                    return;
                }

                if (token.isCancellationRequested) {
                    return;
                }

                progress.report({ increment: 20, message: "生成测试代码..." });

                // 使用配置的模型生成测试代码
                const llm = llmFactory.getLLM(modelName);
                if (!llm) {
                    vscode.window.showErrorMessage(`模型 ${modelName} 未配置，请检查 core/llm-config.json 文件`);
                    Logger.error(`LLM model ${modelName} not found in factory`);
                    return;
                }

                // 验证LLM实例是否有_streamChat方法
                if (typeof llm._streamChat !== 'function') {
                    vscode.window.showErrorMessage(`模型 ${modelName} 不支持流式聊天功能`);
                    Logger.error(`LLM instance does not have _streamChat method: ${llm.constructor.name}`);
                    return;
                }

                Logger.info(`Using LLM model: ${modelName}, instance: ${llm.constructor.name}`);
                const testCode = await this.generateTestCodeWithLLM(llm, promptContext, token, context);

                if (!testCode || token.isCancellationRequested) {
                    return;
                }

                progress.report({ increment: 30, message: "生成测试说明..." });

                // 生成测试说明
                const explanation = await this.generateTestExplanation(llm, promptContext, testCode, token, context);

                if (token.isCancellationRequested) {
                    return;
                }

                progress.report({ increment: 20, message: "分析 GN 文件..." });

                // 准备测试文件路径
                const sourceFilePath = document.uri.fsPath;
                Logger.info(`源文件路径: ${sourceFilePath}`);
                Logger.info(`document.uri: ${document.uri.toString()}`);
                const fileName = path.basename(sourceFilePath);
                const testFileName = fileName.replace(/\.(cpp|cc|cxx|c)$/i, '_test.cpp');
                const workspaceFolder = vscode.workspace.workspaceFolders?.[0];
                if (!workspaceFolder) {
                    vscode.window.showErrorMessage('未找到工作区文件夹');
                    return;
                }

                // 查找 BUILD.gn 文件，确定测试文件位置
                let testFilePath: string;
                let fullTestDir: string;
                let gnChanges = undefined;
                const buildGnPath = GNFileManager.findBuildGnFile(sourceFilePath);
                
                if (buildGnPath) {
                    // 找到了 BUILD.gn，将测试文件生成在 BUILD.gn 所在目录的 test 子目录
                    const buildGnDir = path.dirname(buildGnPath);
                    fullTestDir = path.join(buildGnDir, 'test');
                    testFilePath = path.join(fullTestDir, testFileName);
                    Logger.info(`找到 BUILD.gn 文件: ${buildGnPath}`);
                    Logger.info(`测试文件将生成在 BUILD.gn 同目录的 test/ 子目录: ${testFilePath}`);
                    
                    const gnResult = GNFileManager.addTestFile(buildGnPath, testFilePath);
                    if (gnResult.success) {
                        gnChanges = {
                            filePath: buildGnPath,
                            oldContent: gnResult.oldContent,
                            newContent: gnResult.newContent,
                            diff: gnResult.diff
                        };
                    } else {
                        Logger.warn(`GN 文件修改失败: ${gnResult.message}`);
                    }
                } else {
                    // 未找到 BUILD.gn，使用配置的默认测试目录
                    fullTestDir = path.join(workspaceFolder.uri.fsPath, testDirectory);
                    testFilePath = path.join(fullTestDir, testFileName);
                    Logger.warn('未找到 BUILD.gn 文件，使用默认测试目录: ' + fullTestDir);
                }

                progress.report({ increment: 10, message: "准备预览..." });

                // 提取函数名
                const functionName = (promptContext as any).signature || 'unknown';

                // 构建预览数据
                const previewData: UnitTestPreviewData = {
                    testCode,
                    testFilePath,
                    sourceFilePath: sourceFilePath,
                    functionName,
                    explanation,
                    gnChanges
                };

                // 显示预览面板
                UnitTestPreviewPanel.createOrShow(
                    context.extensionUri,
                    previewData,
                    async (data) => {
                        // 用户接受，保存文件
                        await this.applyTestGeneration(data, testDirectory, context);
                        vscode.window.showInformationMessage('单元测试已成功应用！');
                    },
                    () => {
                        // 用户拒绝
                        vscode.window.showInformationMessage('已取消单元测试生成');
                    }
                );

                progress.report({ increment: 20, message: "完成" });
            });

        } catch (error) {
            Logger.error(`生成单元测试时出错: ${error}`);
            vscode.window.showErrorMessage(`生成单元测试时出错: ${error}`);
        }
    }

    /**
     * 生成测试说明
     * @param llm LLM实例
     * @param promptContext 提示上下文
     * @param testCode 生成的测试代码
     * @param token 取消令牌
     * @param context 扩展上下文
     * @returns 测试说明
     */
    private static async generateTestExplanation(
        llm: BaseLLM,
        promptContext: any,
        testCode: string,
        token: vscode.CancellationToken,
        context: vscode.ExtensionContext
    ): Promise<string> {
        try {
            const functionSignature = promptContext.signature || '';
            const functionCode = promptContext.code || promptContext.targetFunctionCode || '';

            const explanationPrompt = `
作为测试专家，请为下面生成的单元测试提供简洁清晰的说明。

【源函数】
${functionSignature}
${functionCode}

【生成的测试代码】
${testCode}

请用中文提供以下内容（总共不超过300字）：
1. **测试策略**: 简述测试的整体设计思路
2. **测试覆盖**: 说明测试覆盖了哪些场景（正常情况、边界条件、异常情况）
3. **关键测试点**: 指出最重要的测试断言和验证点
4. **GN集成**: 如何将此测试集成到 GN/Ninja 构建系统

请直接给出说明，不要包含额外的格式标记。
`;

            const messages = [
                { role: 'user' as const, content: explanationPrompt }
            ];

            let explanation = '';
            
            // 创建 AbortController 用于取消请求
            const abortController = new AbortController();
            
            // 监听 VSCode 取消令牌
            token.onCancellationRequested(() => {
                abortController.abort();
            });

            for await (const chunk of llm._streamChat(messages, abortController.signal)) {
                if (token.isCancellationRequested) {
                    break;
                }
                
                if (chunk.content) {
                    explanation += chunk.content;
                }
            }

            return explanation.trim() || '测试代码已生成，请根据实际需求调整和完善。';
        } catch (error) {
            Logger.error(`生成测试说明时出错: ${error}`);
            return '测试代码已生成，请根据实际需求调整和完善。';
        }
    }

    /**
     * 应用测试生成（保存文件和更新GN）
     * @param data 预览数据
     * @param testDirectory 测试目录
     * @param context 扩展上下文
     */
    private static async applyTestGeneration(
        data: UnitTestPreviewData,
        testDirectory: string,
        context: vscode.ExtensionContext
    ): Promise<void> {
        try {
            // 1. 保存测试文件
            const testDir = path.dirname(data.testFilePath);
            if (!fs.existsSync(testDir)) {
                fs.mkdirSync(testDir, { recursive: true });
                Logger.info(`创建测试目录: ${testDir}`);
            }

            // 清理测试代码（移除markdown代码块标记）
            let cleanTestCode = data.testCode;
            if (data.testCode.includes('```cpp') || data.testCode.includes('```c++')) {
                cleanTestCode = data.testCode
                    .replace(/```(?:cpp|c\+\+)\n/g, '')
                    .replace(/```\n?$/g, '')
                    .trim();
            }

            fs.writeFileSync(data.testFilePath, cleanTestCode, 'utf8');
            Logger.info(`测试文件已保存到: ${data.testFilePath}`);

            // 2. 应用GN文件变更
            if (data.gnChanges) {
                // 读取当前BUILD.gn内容
                const currentContent = fs.readFileSync(data.gnChanges.filePath, 'utf-8');
                
                // 使用GNFileManager重新生成变更（确保最新）
                const gnResult = GNFileManager.addTestFile(data.gnChanges.filePath, data.testFilePath);
                
                if (gnResult.success) {
                    // 构建完整的新内容
                    const lines = currentContent.split('\n');
                    const targets = GNFileManager.parseTestTargets(data.gnChanges.filePath);
                    
                    if (targets.length > 0) {
                        const target = targets[0];
                        let insertLine = -1;
                        
                        // 找到插入位置
                        for (let i = target.sourcesLine; i < target.endLine; i++) {
                            if (lines[i].includes(']')) {
                                insertLine = i;
                                break;
                            }
                        }
                        
                        if (insertLine >= 0) {
                            const buildGnDir = path.dirname(data.gnChanges.filePath);
                            const relativeTestPath = path.relative(buildGnDir, data.testFilePath).replace(/\\/g, '/');
                            const match = lines[insertLine - 1].match(/^(\s*)/);
                            const indent = match ? match[1] : '    ';
                            const newLine = `${indent}"${relativeTestPath}",`;
                            
                            lines.splice(insertLine, 0, newLine);
                            const newContent = lines.join('\n');
                            
                            fs.writeFileSync(data.gnChanges.filePath, newContent, 'utf-8');
                            Logger.info(`BUILD.gn 文件已更新: ${data.gnChanges.filePath}`);
                        }
                    }
                } else {
                    vscode.window.showWarningMessage(`GN 文件更新失败: ${gnResult.message}`);
                }
            }

            // 3. 打开测试文件
            const testDoc = await vscode.workspace.openTextDocument(data.testFilePath);
            await vscode.window.showTextDocument(testDoc, { preview: false });

        } catch (error) {
            Logger.error(`应用测试生成时出错: ${error}`);
            throw error;
        }
    }

    /**
     * 使用LLM生成测试代码
     * @param llm LLM实例
     * @param promptContext 上下文
     * @param token 取消令牌
     * @param context 扩展上下文
     * @returns 测试代码
     */
    private static async generateTestCodeWithLLM(
        llm: BaseLLM,
        promptContext: any,
        token: vscode.CancellationToken,
        context: vscode.ExtensionContext
    ): Promise<string> {
        try {
            // 构建详细的提示词
            const promptParts = [
                '你是一个专业的C++单元测试生成助手。请为以下C++函数生成完整、可编译的单元测试代码。',
                '',
                '## 待测试函数信息',
                `**函数签名**: ${promptContext.signature || '未知'}`,
                `**源文件路径**: ${promptContext.modulePath || '未知'}`,
                `**是否静态方法**: ${promptContext.is_static_method ? '是' : '否'}`,
                `**是否模板方法**: ${promptContext.is_template_method ? '是' : '否'}`,
                ''
            ];

            // 添加返回类型（如果有）
            if (promptContext.returnType) {
                promptParts.push(`**返回类型**: ${promptContext.returnType}`);
            }

            // 添加所属类（如果有）
            if (promptContext.sourceClass) {
                promptParts.push(`**所属类**: ${promptContext.sourceClass}`);
            }

            promptParts.push(
                '',
                '## 函数源代码',
                '```cpp',
                promptContext.targetFunctionCode || promptContext.code || '',
                '```',
                ''
            );

            // 添加参数定义（如果有）
            if (promptContext.paramDefinitions && promptContext.paramDefinitions.length > 0) {
                promptParts.push('## 参数定义');
                promptContext.paramDefinitions.forEach((p: any) => {
                    promptParts.push(`- ${p}`);
                });
                promptParts.push('');
            }

            // 添加分支信息（如果有）
            if (promptContext.sourceMethodBranchMap && promptContext.sourceMethodBranchMap.length > 0) {
                promptParts.push('## 函数分支信息');
                promptParts.push('该函数包含以下执行路径，请确保测试覆盖这些分支：');
                promptContext.sourceMethodBranchMap.forEach((branch: any, index: number) => {
                    promptParts.push(`${index + 1}. ${JSON.stringify(branch)}`);
                });
                promptParts.push('');
            }

            promptParts.push(
                '## 测试代码生成要求',
                '',
                '### 必须遵守的规则：',
                '1. **完整可编译**：生成的测试代码必须可以直接编译运行',
                '2. **头文件完整**：包含所有必需的头文件（gtest/gtest.h, gmock/gmock.h等）',
                '3. **测试覆盖全面**：',
                '   - 正常情况测试',
                '   - 边界条件测试',
                '   - 异常情况测试（如果适用）',
                '   - 覆盖所有代码分支',
                '4. **Mock使用**：对于依赖外部对象的函数，使用GMock创建Mock对象',
                '5. **断言规范**：使用EXPECT_* / ASSERT_*系列断言',
                '6. **测试结构**：使用TEST或TEST_F宏组织测试用例',
                '7. **命名规范**：测试用例名称应清晰描述测试场景',
                '8. **代码注释**：为每个测试用例添加注释说明测试目的',
                '',
                '### 代码风格要求：',
                '- 遵循Google Test风格指南',
                '- 使用4空格缩进',
                '- 合理组织测试代码结构',
                '',
                '### 输出格式：',
                '- 直接输出完整的C++测试代码',
                '- 使用 ```cpp 代码块包裹',
                '- 不要添加额外的解释说明',
                '',
                '请开始生成测试代码：'
            );

            const prompt = promptParts.join('\n');

            let buffer = '';
            const abortController = new AbortController();
            
            // 监听取消事件
            token.onCancellationRequested(() => {
                abortController.abort();
            });

            // 直接使用 LLM 实例调用（不通过ProxyService，无需登录）
            Logger.info(`Calling LLM._streamChat with prompt length: ${prompt.length}`);
            
            try {
                for await (const message of llm._streamChat(
                    [{ role: 'user', content: prompt }],
                    abortController.signal
                )) {
                    if (token.isCancellationRequested) {
                        break;
                    }
                    if (message && message.content) {
                        buffer += message.content;
                    }
                }
            } catch (streamError) {
                Logger.error(`Error during LLM streaming: ${streamError}`);
                throw new Error(`LLM调用失败: ${streamError instanceof Error ? streamError.message : String(streamError)}`);
            }

            if (!buffer || buffer.trim() === '') {
                vscode.window.showErrorMessage('LLM 未返回测试代码');
                return '';
            }

            return buffer;
        } catch (error) {
            Logger.error(`LLM生成测试代码时出错: ${error}`);
            vscode.window.showErrorMessage(`LLM生成测试代码失败: ${error}`);
            return '';
        }
    }

    /**
     * 保存测试文件
     * @param document 原始文档
     * @param testCode 测试代码
     * @param testDirectory 测试目录
     */
    private static async saveTestFile(
        document: vscode.TextDocument,
        testCode: string,
        testDirectory: string
    ): Promise<void> {
        try {
            // 使用顶部导入的 fs 和 path 模块
            
            // 获取文件信息
            const fileName = path.basename(document.uri.fsPath);
            const testFileName = fileName.replace(/\.(cpp|cc|cxx|c)$/i, '_test.cpp');
            
            // 获取工作区根路径
            const workspaceFolder = vscode.workspace.workspaceFolders?.[0];
            if (!workspaceFolder) {
                vscode.window.showErrorMessage('未找到工作区文件夹');
                return;
            }

            const fullTestDir = path.join(workspaceFolder.uri.fsPath, testDirectory);
            const testFilePath = path.join(fullTestDir, testFileName);

            // 确保测试目录存在
            if (!fs.existsSync(fullTestDir)) {
                fs.mkdirSync(fullTestDir, { recursive: true });
                Logger.info(`创建测试目录: ${fullTestDir}`);
            }

            // 清理测试代码（移除markdown代码块标记）
            let cleanTestCode = testCode;
            if (testCode.includes('```cpp') || testCode.includes('```c++')) {
                cleanTestCode = testCode
                    .replace(/```(?:cpp|c\+\+)\n/g, '')
                    .replace(/```\n?$/g, '')
                    .trim();
            }

            // 保存测试文件
            fs.writeFileSync(testFilePath, cleanTestCode, 'utf8');
            Logger.info(`测试文件已保存到: ${testFilePath}`);

            // 打开测试文件
            const testDoc = await vscode.workspace.openTextDocument(testFilePath);
            await vscode.window.showTextDocument(testDoc, { preview: false });

        } catch (error) {
            Logger.error(`保存测试文件时出错: ${error}`);
            vscode.window.showErrorMessage(`保存测试文件失败: ${error}`);
            throw error;
        }
    }
}
